package cn.exrick.xboot.modules.downloadResources.controller;

import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.timeTask.download.StartDownloadThread;
import cn.exrick.xboot.common.utils.PageUtil;
import cn.exrick.xboot.common.utils.ResultUtil;
import cn.exrick.xboot.common.utils.SpringUtils;
import cn.exrick.xboot.common.utils.jiuqi.utils.Base64EncodingUtil;
import cn.exrick.xboot.common.utils.jiuqi.utils.EncryptUtil;
import cn.exrick.xboot.common.utils.jiuqi.utils.ServeUtil;
import cn.exrick.xboot.common.vo.PageVo;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.modules.downloadResources.entity.DownloadResources;
import cn.exrick.xboot.modules.downloadResources.service.IDownloadResourcesService;
import cn.exrick.xboot.modules.portalConfig.service.IPortalConfigService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author Exrick
 */
@Slf4j
@RestController
@Api(description = "常用资源下载链接管理接口")
@RequestMapping("/xboot/downloadResources")
@Transactional
@CrossOrigin
public class DownloadResourcesController {

    @Autowired
    private IDownloadResourcesService iDownloadResourcesService;
    @Value("${server.port}")
    private String port;
    @Autowired
    private IPortalConfigService iPortalConfigService;
    @RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
    @ApiOperation(value = "通过id获取")
    public Result<DownloadResources> get(@PathVariable String id) {

        DownloadResources downloadResources = iDownloadResourcesService.getById(id);
        return new ResultUtil<DownloadResources>().setData(downloadResources);
    }

    @RequestMapping(value = "/getAll", method = RequestMethod.GET)
    @ApiOperation(value = "获取全部数据")
    public Result<List<DownloadResources>> getAll() {

        List<DownloadResources> list = iDownloadResourcesService.list();
        return new ResultUtil<List<DownloadResources>>().setData(list);
    }

    @RequestMapping(value = "/getByPage", method = RequestMethod.GET)
    @ApiOperation(value = "分页获取")
    public Result<IPage<DownloadResources>> getByPage(@ModelAttribute PageVo page) {
        IPage<DownloadResources> data = iDownloadResourcesService.page(PageUtil.initMpPage(page));
        return new ResultUtil<IPage<DownloadResources>>().setData(data);
    }

    @RequestMapping(value = "/insertOrUpdate", method = RequestMethod.POST)
    @ApiOperation(value = "编辑或更新数据")
    public Result<DownloadResources> saveOrUpdate(@ModelAttribute DownloadResources downloadResources) {
        downloadResources.setUpdateTime(new Date());
        if (iDownloadResourcesService.saveOrUpdate(downloadResources)) {
            return new ResultUtil<DownloadResources>().setData(downloadResources);
        }
        return new ResultUtil<DownloadResources>().setErrorMsg("操作失败");
    }

    @RequestMapping(value = "/delByIds/{ids}", method = RequestMethod.DELETE)
    @ApiOperation(value = "批量通过id删除")
    public Result<Object> delAllByIds(@PathVariable String[] ids) {
        List<DownloadResources>  list=new ArrayList<>();
        for (String id : ids) {
            DownloadResources byId = iDownloadResourcesService.getById(id);
            list.add(byId);
            iDownloadResourcesService.removeById(id);
        }
        //删除的同时开启一个线程用来将本地的资源也同时删除
        StartDownloadThread startDownloadThread=new StartDownloadThread();
        startDownloadThread.setList(list);
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        service.schedule(startDownloadThread, 0, TimeUnit.SECONDS);//秒.
        return new ResultUtil<Object>().setSuccessMsg("批量通过id删除数据成功");
    }

    @RequestMapping(value = "/selectDownloadResourcesPageVoMap", method = RequestMethod.GET)
    @ApiOperation(value = "常用下载资源条件分页获取数据")
    public Result<IPage<DownloadResources>> selectDownloadResourcesPageVoMap(@ModelAttribute Page page, @Param("title") String title, @Param("department") String department) {
        Map<String, Object> map = new HashMap<String, Object>();

        if (title != null && !title.equals("") && title.length() != 0 && !title.trim().isEmpty()) {
            map.put("title", title);
        }
        if (department != null && !department.equals("") && department.length() != 0 && !department.trim().isEmpty()) {
            map.put("department", department);
        }
        IPage<DownloadResources> downloadResourcesIPage = iDownloadResourcesService.selectDownloadResourcesPageVoMap(page, map);
        return new ResultUtil<IPage<DownloadResources>>().setData(downloadResourcesIPage);
    }

    @RequestMapping(value = "/addDownloadResources", method = RequestMethod.POST)
    @ApiOperation(value = "新增保存数据")
    public Result<Object> addDownloadResources(@ModelAttribute DownloadResources downloadResources) {
        downloadResources.setCreateTime(new Date());
        downloadResources.setUpdateTime(new Date());
        boolean save = iDownloadResourcesService.save(downloadResources);
        if (save) {
            return new ResultUtil<Object>().setSuccessMsg("添加成功");
        }
        return new ResultUtil<Object>().setErrorMsg("添加失败");
    }

    @RequestMapping(value = "/singlefile", method = RequestMethod.POST)
    public Object singleFileUpload(MultipartFile file, @Param("title") String title, @Param("department") String department) {
            log.info("开始上传文件：" + file.getOriginalFilename());
            log.info("传入的文件参数：{}:" + file.getOriginalFilename());
            log.info("测试接受参数:" + title);
            log.info("测试接受参数:" + department);
           // String newFileName=null;
            if (Objects.isNull(file) || file.isEmpty()) {
            log.error("文件为空");
            return new ResultUtil<Object>().setErrorMsg("文件为空，请重新上传");
            //return "文件为空，请重新上传";
        }
        String fileName= file.getOriginalFilename();
       /* try {
            //fileName=new String(fileName.getBytes(),"ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }*/
        try {

            //1.上传文件
            //获取服务器资源路径
            String filepath= iPortalConfigService.selectPortalConfigByKey("fileUpdate").getValue();
            log.info("获取服务器资源路径:"+filepath);
            byte[] bytes = file.getBytes();

           /* //文件后缀
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            // 新文件名（唯一）
             newFileName = new Date().getTime() + "." + suffix;
            log.info("新文件名（唯一）:"+newFileName);*/
            Path path = Paths.get(filepath + fileName);
            //如果没有files文件夹，则创建
            if (!Files.isWritable(path)) {
                Files.createDirectories(Paths.get(filepath));
            }
            //文件写入指定路径
            Path write = Files.write(path, bytes);
            log.debug("文件写入成功...");

        } catch (IOException e) {
            return new ResultUtil<Object>().setErrorMsg("文件上传失败");
            //return "文件上传失败";
        }
        //2.将上传文件信息存储到常用下载目录中
        String IP="127.0.0.1";
        try {
            /*InetAddress address = InetAddress.getLocalHost();//获取的是本地的IP地址
            IP = address.getHostAddress();//192.168.0.121*/
            IP = ServeUtil.getInet4Address();
            java.lang.System.out.println("ip地址:"+IP);

        //使用加密的文件名解决访问地址出现特殊符号问题 njp 20200118
            fileName= Base64EncodingUtil.encryptBASE64(fileName);
         log.info("地址加密结果"+fileName);
             } catch (Exception e) {
                 e.printStackTrace();
         }

        /**
         *  njp 20200224获取资源服务器的port的改造 begin
         */
        String  fileProjectPort =ServeUtil.getFilrProject();
        /**
         *  njp 20200224 获取资源服务器的port的改造 end
         */
        String fileUrl="http://"+IP+":"+fileProjectPort+"/xboot/downloadResources/downloadFile?fileName="+fileName;
        DownloadResources downloadResources = new DownloadResources();
        Date date = new Date();
        downloadResources.setCreateTime(date);
        downloadResources.setUpdateTime(date);
        downloadResources.setTitle(title);
        downloadResources.setDepartment(department);
        downloadResources.setUrl(fileUrl);
        downloadResources.setFileName(file.getOriginalFilename());
        downloadResources.setNewfileName(fileName);
        boolean save = iDownloadResourcesService.save(downloadResources);
        if (save) {
            return new ResultUtil<Object>().setSuccessMsg("文件上传成功");
        }
        return new ResultUtil<Object>().setErrorMsg("文件上传失败");

        //return "文件上传失败";
    }

    @RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
    private String downloadFile(HttpServletResponse response,@Param("fileName") String fileName,HttpServletRequest request) {
        log.info("开始下载");
        String userAgent = request.getHeader("user-agent").toLowerCase();
        String filepath=null;
        try{
            //开始解密
            fileName=Base64EncodingUtil.decryptBASE64(fileName);
            log.info("下载文件名"+fileName);
        //获取服务器资源路径
        IPortalConfigService iPortalConfigService = (IPortalConfigService) SpringUtils.getBean("IPortalConfigServiceImpl");
         filepath= iPortalConfigService.selectPortalConfigByKey("fileUpdate").getValue()+fileName;
        log.info("获取服务器资源路径:"+filepath);
        }catch (Exception e){
            e.printStackTrace();
            return "下载失败";
        }
        String downloadFilePath = filepath;//被下载的文件在服务器中的路径,
        //String fileName = "20190930.sql";//被下载文件的名称

        File file = new File(downloadFilePath);
        if (file.exists()) {
            long length = file.length();
            response.setContentType("application/force-download");// 设置强制下载不打开            
            //response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            String utfFileName=null;
            try {
                 //utfFileName=new String(fileName.getBytes(),"ISO-8859-1");
                //utfFileName=new String(fileName.getBytes(),"UTF-8");
                if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {
                    // win10 ie edge 浏览器 和其他系统的ie
                    utfFileName = URLEncoder.encode(fileName, "UTF-8");
                } else {
                    // 其他
                    utfFileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.addHeader("Content-Disposition", "attachment;fileName=" + utfFileName);
            //response.setDateHeader("Content-Length",length);
            response.setHeader("Content-Length",String.valueOf(length));
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                
                bis = new BufferedInputStream(fis);
                OutputStream outputStream = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    outputStream.write(buffer, 0, i);
                    i = bis.read(buffer);
                    //outputStream.flush();
                }
                return "下载成功";
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return "下载失败";
    }

}
